// 只做一层拷贝

export interface NodeType {
  id: string;
  parentId?: string;
  // 排序
  sort?: number;
}

export type TreeNode<T extends NodeType = any> = Omit<
  T,
  'originNode' | 'level' | 'children' | 'parentNode' | 'sort'
> & {
  originNode: T;
  // 等级
  level: number;
  // 子节点
  children?: TreeNode<T>[];
  // 父节点引用
  parentNode: ParentNode<T> | RootNode<T>;
  // 排序结果
  sort: number;
};

type RootNode<T extends NodeType = any> = Readonly<{ children: TreeNode<T>[] }>;
type ParentNode<T extends NodeType = any> = Omit<TreeNode<T>, 'children'> & {
  children: TreeNode<T>[];
};

function _flat2Tree<T extends NodeType = any>(
  flatArr: T[],
  parentNode: ParentNode<T>,
) {
  const childNodes: TreeNode<T>[] = flatArr
    .filter((v) => v.parentId === parentNode.id)
    .map<TreeNode<T>>((child, sort) => {
      return {
        sort,
        ...child,
        originNode: child,
        level: parentNode.level + 1,
        parentNode: parentNode,
      };
    })
    .sort((a, b) => {
      return a.sort - b.sort;
    });

  if (childNodes.length === 0) {
    return;
  } else {
    childNodes.forEach((node) => {
      node.children = _flat2Tree(flatArr, node as ParentNode<T>);
    });
    return childNodes;
  }
}

function flat2Tree<T extends NodeType = any>(flatArr: T[], rootId?: string) {
  let rootNode: RootNode<T> = { children: [] };

  const parentNodes: TreeNode<T>[] = flatArr
    .filter((v) => v.parentId === rootId)
    .map<TreeNode<T>>((node, sort) => {
      return {
        sort,
        ...node,
        originNode: node,
        level: 0,
        parentNode: rootNode,
      };
    })
    .sort((a, b) => {
      return a.sort - b.sort;
    });

  parentNodes.forEach((node) => {
    node.parentNode = rootNode;
    node.children = _flat2Tree(flatArr, node as ParentNode<T>);
  });

  if (parentNodes.length === 0) {
    return [];
  } else {
    rootNode.children.push(...parentNodes);
    return parentNodes;
  }
}

export { flat2Tree };
